home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / help.zip / HELPCONV / MAIN.C < prev    next >
C/C++ Source or Header  |  1992-03-26  |  18KB  |  819 lines

  1. #define LEN 256
  2. #define ORDERED 1
  3. #define SIMPLE  2
  4. #define BULLET 3
  5.  
  6. #include <ctype.h>
  7. #define TRUE 1
  8. #define FALSE 0
  9.  
  10. char chdtText[LEN];
  11. char chdthdText[LEN];
  12. char chAppendBuffer[LEN * 4];
  13.  
  14. int  append = 0;
  15. int bExample = FALSE;
  16. int num_styles = 0;
  17. int ii_lineno = 1;
  18. int ii_list_type = 0;
  19. int ii_list_order = 1;
  20. int bfirst = TRUE;
  21.  
  22. FILE *fp_rtf, *fp_ipf, *fp_err;
  23.  
  24.  
  25. int isstring(ch)
  26.     char ch;
  27.     {
  28.     if ( isalnum(ch) || ((ch) == '_') || ((ch) == ' '))
  29.         return(TRUE);
  30.     else
  31.         return(FALSE);
  32.     }
  33.  
  34. //
  35. // Main will take 1 or two arguements.
  36. // With no arguements, the input file is assumed to be 'sample.ipf'
  37. // The first arguement [if it exists] is the input file name.
  38. // The second arguement, regardless of what it is, specifies
  39. // 'debug mode' which prints tokens as they are read and intermixes
  40. // this with the RTF output.
  41. //
  42. // The output is always out.rtf.
  43. // stderr may be redirected.  The default is the console.
  44. //
  45. main( argc, argv)
  46.     int argc;
  47.     char *argv[];
  48.     {
  49.     int ii;
  50.     int ii_token;
  51.     int ii_prev_token = 0;
  52.     char *input;
  53.     int debug = FALSE;
  54.  
  55.     memset( chAppendBuffer, 0x00, LEN * 4);
  56.  
  57.     ii = 0;
  58.  
  59.     if (argc > 1)
  60.         input = argv[1];
  61.     else
  62.         input = "sample.ipf";
  63.  
  64.     if (argc > 2)
  65.         debug = TRUE;
  66.  
  67.     fp_ipf = freopen( input, "rt", stdin);
  68.     fp_rtf = freopen( "out.rtf", "w", stdout);
  69.     fp_err = stderr;
  70.  
  71.     //
  72.     // Opening RTF commands.  Note that :userdoc is ignored when found.
  73.     //
  74.     do_begin();
  75.  
  76.     while (ii_token = yylex())
  77.         {
  78.  
  79.         //
  80.         // Comments are eaten, thereby cleaning up debug output.
  81.         // The newline following the comment is eaten here as well.
  82.         //
  83.         if (ii_token == COMMENT)
  84.             {
  85.             if ((ii_token = yylex()) == NL)
  86.                 {
  87.                 ii_lineno++;
  88.                 ii_token = yylex();
  89.                 }
  90.             }
  91.  
  92.         //
  93.         // Print that token if we are debugging.
  94.         //
  95.         if (debug)
  96.             debug_token( fp_rtf, ii_token);
  97.  
  98.         //
  99.         // 'Append' mode is only entered when processing
  100.         // hypertext *outside* of a list item.
  101.         //
  102.         // We customize the parsing of hypertext and we need the
  103.         // entire string from :hpt thru :ehpt.
  104.         //
  105.         if ( append )
  106.             {
  107.             if ( ii_token == EHPT )
  108.                 {
  109.                 append = 0;
  110.                 }
  111.             else
  112.                 strcat( chAppendBuffer, yytext);
  113.  
  114.             continue;
  115.             }
  116.  
  117.         switch( ii_token)
  118.             {
  119.             case COMMENT:    break;
  120.  
  121.             // Note that the new line will not effect the text.
  122.             case COLON:      fprintf( fp_rtf, ":\n", yytext); break;
  123.  
  124.             // A newline is treated as whitespace in IPF, but not
  125.             // RTF.  Insert that space!
  126.             case NTEXT:      fprintf( fp_rtf, "%s \n", yytext); break;
  127.             
  128.             // I keep track of newlines but don't use it yet.
  129.             // enhanced error reporting needs this.
  130.             case NL:        
  131.                 ii_lineno++;
  132.                 if (bExample)
  133.                     fprintf( fp_rtf, "\\par\n", yytext);
  134.                 break;
  135.  
  136.             case HDR:        do_hdr();    break;
  137.  
  138.             // Windows help doesn't differentiate between primary
  139.             // and secondary indexes.
  140.             case NDX1:       do_ndx();    break;
  141.             case NDX2:       do_ndx();    break;
  142.  
  143.             case HPT:        append = 1;    break;
  144.             case EHPT:       break;
  145.  
  146.             case PARA:       fprintf( fp_rtf, "\\par\n");    break;
  147.  
  148.             case FNREF:      do_hpt( 1);    break;
  149.             case HDREF:      do_hpt( 2);    break;
  150.  
  151.             case STYLE:      do_style();    break;
  152.             case ESTYLE:     do_estyle();    break;
  153.  
  154.             // I do not honor margin requests at present.
  155.             // Partly because I don't know how to convert from
  156.             // IPF margin amounts to the correct figure in
  157.             // twips.
  158.             case MARGIN:     break;
  159.  
  160.             // I do not honor 'nt' commands, except to insert this
  161.             // string.
  162.             case NOTE:       fprintf( fp_rtf, "Note: ");    break;
  163.             case ENOTE:      break;
  164.  
  165.             // I can do nothing for examples, really.
  166.             case XMP:        do_xmp();    break;
  167.             case EXMP:       do_exmp();  break;
  168.  
  169.             // I ignore the compact option, as well as lists-in-lists.
  170.             // This handles simple, ordered, and bullet lists.
  171.             case SL:         do_list();    break;
  172.             case SLC:        do_list();    break;
  173.  
  174.             case DL:         break;
  175.  
  176.             case EDL:        
  177.             case ESL:        
  178.             case EPARML:
  179.                 do_endlist();
  180.                 break;
  181.  
  182.             // Save the dthd text.
  183.             case DTHD:       
  184.                 while ((ii_token = yylex()) != NTEXT) ;
  185.                 strcpy( chdthdText, yytext); 
  186.                 break;
  187.  
  188.             // this requires a preceeding dthd.
  189.             case DDHD:       
  190.                 while ((ii_token = yylex()) != NTEXT) ;
  191.                 do_ddhd();    
  192.                 break;
  193.             // Process a list item.  This gets involved due to
  194.             // embedded styles and hypertext.
  195.             case LI:         do_li(ii_list_type);    break;
  196.             case DT:         do_li(DT); break;
  197.             case DD:         do_li(DD); break;
  198.  
  199.             case PARML:      break;
  200.             case PT:         break;
  201.             case PD:         break;
  202.  
  203.             // runin is ignored.
  204.             case ARTWORK:    do_art(); break;
  205.  
  206.             case FN:         do_fn();    break;
  207.             case EFN:        fprintf( fp_rtf, "\\par\n");    break;
  208.             case USERDOC:    break;
  209.             case EUSERDOC:    fprintf( fp_rtf, "}");    return(0);
  210.             }
  211.  
  212.         // historical, and it might be useful one day.
  213.         ii_prev_token = ii_token;
  214.  
  215.         }
  216.     }
  217.  
  218. //
  219. // Process an index command.
  220. //
  221. do_ndx()
  222.     {
  223.     char chName[LEN];
  224.     char chBuffer[LEN];
  225.     int  ii = 0;
  226.     char ch;
  227.     char *pchsource;
  228.     char *pchdest;
  229.  
  230.  
  231.     pchsource = yytext;
  232.  
  233.     //
  234.     // Looking for the ending '.' of the tag.  This position differs between
  235.     // primary and secondary indexes.
  236.     //
  237.     while ( *pchsource++ != '.') ;
  238.     pchdest = chBuffer;
  239.     while (isstring(ch = *pchsource++))
  240.         {
  241.         *pchdest++ = ch;
  242.         }
  243.     *pchdest = 0x00;
  244.  
  245.     fprintf( fp_rtf, "K{\\footnote %s}\n", chBuffer);
  246.     }
  247.  
  248. //
  249. // What type of list is it?
  250. //
  251. do_list()
  252.     {
  253.  
  254.     switch( yytext[1])
  255.         {
  256.         case 'u':
  257.             ii_list_type = BULLET;
  258.             break;
  259.         case 'o':
  260.             ii_list_type = ORDERED;
  261.             break;
  262.         case 's':
  263.         default:
  264.             ii_list_type = SIMPLE;
  265.         }
  266.  
  267.     }
  268. #define LIST_FORMAT() \
  269. fprintf( fp_rtf, "\\par\n\\pard\\fi-240\\li300\\tx300\\ri120\\sb60\n")
  270.  
  271. // 
  272. // Process a nice, harry header line.
  273. //
  274. do_hdr()
  275.     {
  276.     char chName[LEN];
  277.     char chBuffer[LEN];
  278.     int  ii = 0;
  279.     char ch;
  280.     char *pchsource;
  281.     char *pchdest;
  282.  
  283.  
  284.     // Obtain the ID of the header.
  285.     get_id( chName, "Header", yytext);
  286.  
  287.     // This assumes the name of the header is on the same line
  288.     // as the :h tag.
  289.     pchsource = yytext;
  290.     while ( *pchsource++ != '.') ;
  291.     pchdest = chBuffer;
  292.     while (isstring(ch = *pchsource++))
  293.         {
  294.         *pchdest++ = ch;
  295.         }
  296.     *pchdest = 0x00;
  297.     if (!bfirst)
  298.         {
  299.         fprintf( fp_rtf, "\\page\n");
  300.         }
  301.     else
  302.         bfirst = FALSE;
  303.  
  304.     fprintf( fp_rtf, "\\pard\\sb120\\f2\\fs20\\li60\\ri60\n");
  305.     fprintf( fp_rtf, "${\\footnote %s}\n", chBuffer);
  306. //    fprintf( fp_rtf, "K{\\footnote %s}\n", chBuffer);
  307.     fprintf( fp_rtf, "#{\\footnote %s}\n", chName);
  308.     }
  309.  
  310. //
  311. //  Handle hypertext outside of a list item.
  312. //
  313. do_hpt( flag)
  314.     int flag;
  315.     {
  316.     char chBuffer[LEN];
  317.  
  318.     get_id( chBuffer, "Hypertext", yytext);
  319.     fprintf( fp_rtf, "{\\ul");
  320.     if ( flag == 2)
  321.         fprintf( fp_rtf, "db ");
  322.     else
  323.         fprintf( fp_rtf, " ");
  324.  
  325.     fprintf( fp_rtf, "%s}{\\v %s} \n", chAppendBuffer, chBuffer);
  326.     memset( chAppendBuffer, 0x00, LEN * 4);
  327.  
  328.     }
  329.  
  330. #if 0
  331. get_name(pchName, pchError)
  332.     char *pchName;
  333.     char *pchError;
  334.     {
  335.     int ii = 0;
  336.     char ch;
  337.  
  338.     while ( yytext[ii] && yytext[ii] != '=' ) ii++;
  339.     if ( yytext[ii] != '=')
  340.         {
  341.         fprintf(fp_err, "Error parseing %s\n", pchError);
  342.         }
  343.     ii++;
  344.     while ( ch = yytext[ii] )
  345.         {
  346.         if ( isalnum(ch))
  347.             {
  348.             *pchName++ = ch;
  349.             }
  350.         ii++;
  351.         }
  352.     *pchName = 0x00;
  353.     }
  354.  
  355. #endif
  356.  
  357. //
  358. // Place a ID name [precedded by an '=']
  359. // in pchName from the string pchSource
  360. // and write an error message based on pchError if you don't find it.
  361. //
  362. get_id(pchName, pchError, pchSource)
  363.     char *pchName;
  364.     char *pchError;
  365.     char *pchSource;
  366.     {
  367.     int ii = 0;
  368.     char ch;
  369.  
  370.     while ( *pchSource && *pchSource != '=' ) pchSource++;
  371.     if ( *pchSource != '=')
  372.         {
  373.         //
  374.         // List processing now has some error recovery, and
  375.         // a way of handling this error so it doesn't want the
  376.         // error message in that case.
  377.         //
  378.         if (pchError)
  379.             fprintf(fp_err, "Error parseing %s\n", pchError);
  380.         return(-1);
  381.         }
  382.  
  383.     pchSource++;
  384.     while ( isalnum(ch = *pchSource) || *pchSource == '_')
  385.         {
  386.         *pchName++ = ch;
  387.         pchSource++;
  388.         }
  389.     *pchName = 0x00;
  390.     return(0);
  391.     }
  392.  
  393. // do a footnote.
  394. do_fn()
  395.     {
  396.     char chBuffer[256];
  397.     char ch;
  398.  
  399.     get_id( chBuffer, "Footnote", yytext);
  400.  
  401.     fprintf( fp_rtf, "\\page\n\\pard\\sb120\\f2\\fs20\\li60\\ri60\n");
  402.     fprintf( fp_rtf, "#{\\footnote %s}", chBuffer);
  403.     }
  404.  
  405. do_endlist()
  406.     {
  407.     ii_list_order = 1;
  408.     ii_list_type  = 0;
  409.     fprintf( fp_rtf, "\\par\n\\pard\\li60\\ri60\\sb120\n");
  410.     }
  411.  
  412. //
  413. // Search the RTF file for MS_MS to locate example code.
  414. //
  415. do_xmp()
  416.     {
  417.     bExample = TRUE;
  418.     fprintf( fp_rtf, "\\sb0\\par\n\\pard\\f5\\li300\\ri120\\keep\n");
  419.     fprintf( fp_rtf, "MS_MS Example follows:\\par\n");
  420.     }
  421.  
  422. do_exmp()
  423.     {
  424.     bExample = FALSE;
  425.     fprintf( fp_rtf, "\\keep\\par\\pard");
  426.     }
  427.  
  428. // unwind those styles!
  429. do_estyle()
  430.     {
  431.     while ( num_styles > 0)
  432.         {
  433.         num_styles--;
  434.         fprintf( fp_rtf, "}");
  435.         }
  436.     fprintf( fp_rtf, "\n");
  437.     }
  438.  
  439. // establish style type and begin it appropriately
  440. do_style()
  441.     {
  442.     char ch;
  443.     int  ii_style;
  444.  
  445.     ii_style  = yytext[3] - '0';
  446.  
  447.     switch (ii_style)
  448.         {
  449.         case 1:
  450.             num_styles += 1;
  451.             fprintf( fp_rtf, "{\\i ");
  452.             break;
  453.         case 2:
  454.             num_styles += 1;
  455.  
  456.             fprintf( fp_rtf, "{\\b ");
  457.             break;
  458.         case 3:
  459.             num_styles += 2;
  460.  
  461.             fprintf( fp_rtf, "{\\b {\\i ");
  462.             break;
  463.         case 5:
  464.             num_styles = +1;
  465.  
  466.             fprintf( fp_rtf, "{\\ul ");
  467.             break;
  468.         default:
  469.             fprintf( fp_err, "Unknown Style %d\n", ii_style);
  470.         }
  471.  
  472.     }
  473.  
  474.  
  475. do_ddhd()
  476.     {
  477.     fprintf( fp_rtf, "\\par\\pard\\sb120\\fi-1568\\li1628\\tx1628");
  478.     fprintf( fp_rtf, "\\ri120\\brdrb\\brdrs\n");
  479.     fprintf( fp_rtf, "{%s \\tab %s}\n", chdthdText, yytext);
  480.     }
  481.  
  482.  
  483. do_art( )
  484.     {
  485.     int ii = 0;
  486.     int jj = 6;
  487.     char chBuffer[256];
  488.     char ch;
  489.     int  bPeriod = FALSE;
  490.  
  491.     while ( yytext[ii] && yytext[ii] != '=' ) ii++;
  492.     if ( yytext[ii] != '=')
  493.         {
  494.         fprintf(fp_err, "Error parseing Artwork\n");
  495.         }
  496.     ii++;
  497.     sprintf( chBuffer, "\\{bmc ");
  498.     while ( ch = yytext[ii] )
  499.         {
  500.         if (ch == '.')
  501.             if (!bPeriod)
  502.                 {
  503.                 chBuffer[jj++] = ch;
  504.                 bPeriod = TRUE;
  505.                 }
  506.         if ( isalpha(ch) )
  507.             {
  508.             chBuffer[jj++] = ch;
  509.             }
  510.  
  511.         if (ch == ' ')
  512.             {
  513.             yytext[ii] = 0x00;
  514.             }
  515.         else
  516.             ii++;
  517.         }
  518.     chBuffer[jj] = 0x00;
  519.     fprintf( fp_rtf, "%s\\}\n", chBuffer);
  520.     }
  521.  
  522. do_begin()
  523.     {
  524.     fprintf( fp_rtf, "{\\rtf1\\ansi\n");
  525.     fprintf( fp_rtf, "{\\fonttbl\n");
  526.     fprintf( fp_rtf, "{\\f0\\froman Tms Rmn; }\n");
  527.     fprintf( fp_rtf, "{\\f1\\fdecor Courier; }\n");
  528.     fprintf( fp_rtf, "{\\f2\\fswiss Helv; }\n");
  529.     fprintf( fp_rtf, "{\\f3\\fdecor ZapfDingbats; }\n");
  530.     fprintf( fp_rtf, "{\\f4\\fdecor Symbol; }\n");
  531.     fprintf( fp_rtf, "{\\f5\\fmodern Courier; }\n");
  532.     fprintf( fp_rtf, "}\n");
  533.     fprintf( fp_rtf, "{\\colortbl;\n");
  534.     fprintf( fp_rtf, "\\red0\\green0\\blue0;\\red255\\green0\\blue0;");
  535.     fprintf( fp_rtf, "\\red0\\green128\\blue0;\\red0\\green0\\blue255;");
  536.     fprintf( fp_rtf, "}\n");
  537.     }
  538.     
  539. #ifdef DEBUG
  540. #include "dbgtok.h"
  541. #endif
  542.  
  543. char yytmp[YYLMAX];
  544.  
  545. //
  546. // The situation: while processing a list item I discover that
  547. // it is incomplete, and some formatting is on the next line.
  548. //
  549. // I need to get the next line, regardless of its token value,
  550. // and append to my current text.
  551. //
  552. // This is designed to do that.
  553. //
  554. int append_token(ii_nl)
  555.     int ii_nl;
  556.     {
  557.     int ii_new = 0;
  558.  
  559.     yytmp[0] = 0x00;
  560.     strcpy( yytmp, yytext);
  561.     while (ii_nl) 
  562.         {
  563.         ii_new = yylex();
  564.         if (ii_new != NL)
  565.             strcat( yytmp, yytext);
  566.         else
  567.             {
  568.             strcat( yytmp, " ");
  569.             ii_nl--;
  570.             ii_lineno++;
  571.             }
  572.         }
  573.  
  574.     strcpy( yytext, yytmp);
  575.     return(ii_new);
  576.     }
  577.  
  578.  
  579. //
  580. // List items: Complex parsing!
  581. //
  582. do_li(list_type)
  583.     int list_type;
  584.     {
  585.     char *pchsource = yytext + 4;
  586.     char chListText[LEN];
  587.     char *pchList = chListText;
  588.     char chRefText[LEN];
  589.     char *pchRef = chRefText;
  590.     char chHyperText[LEN];
  591.     char *pchHyper = chHyperText;
  592.     char chHyperLinkBuffer[LEN];
  593.     char chBuffer[LEN];
  594.     char ch;
  595.     int  bHyper = FALSE;
  596.     int  bRef   = FALSE;
  597.     int  ii_type = 0;
  598.  
  599.     memset( chListText, 0x00, LEN);
  600.     *pchRef  = 0x00;
  601.     *pchHyper = 0x00;
  602.  
  603.     // Parse the input string into the output list buffer.
  604.     while ( ch = *pchsource++)
  605.         {
  606.         // Copy if it isn't a tag
  607.         if (ch != ':' )
  608.             {
  609.             *pchList++ = ch;
  610.             }
  611.         // a hypertext reference. 
  612.         else if (    ( strncmp( pchsource, "hdref", 5) == 0)
  613.                   || ( strncmp( pchsource, "fnref", 5) == 0) )
  614.             {
  615.             if (bHyper == FALSE)
  616.                 {
  617.                 fprintf( fp_err, "No Hypertext!");
  618.                 *pchHyper = 0x00;
  619.                 }
  620.  
  621.             if (*pchsource == 'h')
  622.                 ii_type = 1;
  623.  
  624.             //
  625.             // Find the ID.  If you don't find it the first time,
  626.             // go to next line to find it.
  627.             //
  628.             if (get_id( chRefText, NULL, pchsource))
  629.                 {
  630.                 append_token(2);
  631.                 if (get_id( chRefText, "Embedded Reference", pchsource))
  632.                       exit(-1);
  633.                 }
  634.  
  635.             strcpy( chBuffer, "{\\ul");
  636.             if (ii_type == 1)
  637.                 strcat( chBuffer, "db");
  638.  
  639.             //
  640.             // This is a little extra fancy since I am accumulating
  641.             // a text string in chListText instead of doing direct
  642.             // RTF output.
  643.             //
  644.             sprintf( chHyperLinkBuffer, "%s %s}{\\v %s}",
  645.                     chBuffer, chHyperText, chRefText);
  646.             strcat( chListText, chHyperLinkBuffer);
  647.             pchList = chListText + strlen( chListText);
  648.             chHyperText[0] = 0x00;
  649.             chHyperLinkBuffer[0] = 0x00;
  650.             pchHyper = chHyperText;
  651.             bHyper = FALSE;
  652.  
  653.             // copy till we find the ending period.
  654.             do    
  655.                 {
  656.                 ch = *pchsource++;
  657.                 } while (ch && ch != '.');
  658.             if ( ch == 0x00)
  659.                 pchsource--;
  660.             }
  661.         // end style
  662.         else if (strncmp( pchsource, "ehp", 3) == 0)
  663.             {
  664.             while ( num_styles > 0)
  665.                 {
  666.                 num_styles--;
  667.                 *pchList++ = '}';
  668.                 }
  669.             pchsource += 5;
  670.             }
  671.  
  672.         // Begin a style
  673.         else if ( *pchsource       == 'h' &&
  674.                   *(pchsource + 1) == 'p' &&
  675.                   isdigit(*(pchsource + 2)))
  676.             {
  677.             switch ( *(pchsource + 2) )
  678.                 {
  679.                 case '1':
  680.                     num_styles += 1;
  681.                     strcat( pchList - 1, "{\\i ");
  682.                     pchList += 4;
  683.                     break;
  684.                 case '2':
  685.                     num_styles += 1;
  686.                     strcat( pchList - 1, "{\\b ");
  687.                     pchList += 4;
  688.                     break;
  689.                 case '3':
  690.                     num_styles += 2;
  691.                     strcat( pchList - 1, "{\\b {\\i ");
  692.                     pchList += 8;
  693.                     break;
  694.                 case '5':
  695.                     num_styles += 1;
  696.                     strcat( pchList - 1, "{\\ul ");
  697.                     pchList += 5;
  698.                     break;
  699.                 default:
  700.                     fprintf( fp_err, "Unknown Style in List\n");
  701.  
  702.                 }
  703.             pchsource += 4;    
  704.             }
  705.         // Begin hypertext
  706.         else if ( strncmp( pchsource, "hpt.", 4) == 0)
  707.             {
  708.             bHyper     = TRUE;
  709.             pchsource += 4;
  710.             do
  711.                 {
  712.                 ch = *pchsource++;
  713.  
  714.                 if (ch != ':')
  715.                     *pchHyper++ = ch;
  716.                 else if ( strncmp( pchsource, "ehpt.", 5) == 0)
  717.                     {
  718.                     pchsource += 5;
  719.                     *pchHyper = 0x00;
  720.                     ch        = 0x00;
  721.                     }
  722.                 else
  723.                     {
  724.                     fprintf( fp_err, "Unexpected Token", pchsource);
  725.                     *pchHyper = 0x00;
  726.                     ch        = 0x00;
  727.                     }
  728.                 } while (ch != 0x00);
  729.             }
  730.         }
  731.  
  732.     // Now that we have a complex output buffer, format it
  733.     // properly for the type of list we are processing.
  734.     switch (list_type)
  735.         {
  736.         case BULLET:
  737.             LIST_FORMAT();
  738.             fprintf( fp_rtf, "\\{bmc bullet.bmp\\}\n\\tab\n%s\n",
  739.                 chListText);
  740.             break;
  741.         case ORDERED:
  742.             fprintf( fp_rtf, "\\par\n");
  743.             LIST_FORMAT();
  744.             fprintf( fp_rtf, "%d\n\\tab\n", ii_list_order++);
  745.             fprintf( fp_rtf, "%s\n", chListText);
  746.             break;
  747.  
  748.         case SIMPLE:
  749.             fprintf( fp_rtf, "\\par\n");
  750.             LIST_FORMAT();
  751.             fprintf( fp_rtf, "%s\n", chListText);
  752.             break;
  753.         case DD:
  754.             fprintf( fp_rtf, "\\par\n\\pard\\fi-1568\\li1628\\tx1628");
  755.             fprintf( fp_rtf, "\\ri120\\sb60\n{%s}\n\\tab\n%s \n", 
  756.                 chdtText, chListText);
  757.             break;
  758.         case DT:
  759.             strcpy( chdtText, chListText);
  760.             break;
  761.  
  762.         }
  763.     }
  764.  
  765. // A debug print routine.
  766. debug_token( fp, ii)
  767.     FILE *fp;
  768.     int   ii;
  769.     {
  770.     switch( ii)
  771.         {
  772.         case NL:
  773.         case COMMENT:
  774.             break;
  775.  
  776.         case COLON:
  777.         case NTEXT:
  778.         case HDR:
  779.         case NDX1:
  780.         case NDX2:
  781.         case HPT:
  782.         case EHPT:
  783.         case PARA:
  784.         case FNREF:
  785.         case HDREF:
  786.         case STYLE:
  787.         case ESTYLE:
  788.         case MARGIN:
  789.         case NOTE:
  790.         case ENOTE:
  791.         case XMP:
  792.         case EXMP:
  793.         case LI:
  794.         case SL:
  795.         case SLC:
  796.         case DL:
  797.         case EDL:        
  798.         case ESL:        
  799.         case EPARML:
  800.         case DTHD:
  801.         case DDHD:
  802.         case DT:
  803.         case DD:
  804.         case PARML:
  805.         case PT:
  806.         case PD:
  807.         case ARTWORK:
  808.         case FN:
  809.         case EFN:
  810.         case USERDOC:
  811.         case EUSERDOC:
  812.             fprintf( fp, "##%s {{%s}}\n", pch_token_string[ii], yytext);
  813.             break;
  814.         default:
  815.             break;
  816.         }
  817.     }
  818.  
  819.